﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using GSN;


namespace IndustryWrapper
{
    /// <summary>
    /// 控制卡的类型
    /// </summary>
    public enum EGsnCardType
    {
        G800=1,
        V800=2,
        V24=3,
        G24=4
    }
    /// <summary>
    /// 扩展模块的名称
    /// </summary>
    public enum EGsnModelType
    {
        M40300=1,
        M60200=2,
        M40200=3,
        M40301=4,
        M4XX=5,
        M6XX=6
    }
    /// <summary>
    /// 可以接的模块的名称
    /// </summary>
    public enum EGsnIoType
    {
        ACC1616D = 1,//16的IO模块
        ACC0604A = 2//模拟量模块
    }
    /// <summary>
    /// 扩展模块的SHUJU
    /// </summary>
    public class CCfgIoDataGsn
    {
        public int id = 0;//模块地址
        public EGsnIoType ioType = EGsnIoType.ACC1616D;
    }
    /// <summary>
    /// GSN的配置文件
    /// 一个核一个文件
    /// </summary>
    public class CCfgDataGsn
    {
        public EGsnCardType cardType = EGsnCardType.G800;//控制卡类型
        public bool initreset = true;//这个核是否需要复位
        public bool uninitReset = true;//关闭的时候是否需要初始化
        public string cardConfigeFn = "Core1.CFG";//这个核的配置文件名称
        public List<EGsnModelType> axisModelList = new List<EGsnModelType>();//总共挂了哪些轴模块
        //扩展模块的配置
        public string extIoFn = "";//扩展模块的配置文件,如果="",代表没有扩展模块.
        public List<CCfgIoDataGsn> extIoList = new List<CCfgIoDataGsn>();//IO类型列表
    }
    /// <summary>
    /// GSN的配置文件
    /// </summary>
    public class CCfgGsn : CMotionConfigeBase
    {
        public List<CCfgDataGsn> cfg = new List<CCfgDataGsn>();
        /// <summary>
        /// 导出配置中所有的轴到excel的轴列表中
        /// </summary>
        /// <param name="csv"></param>
        /// <returns></returns>
        public override bool exportAxisToCsv(string csv)
        {
            List<string> msg = new List<string>();
            int core = 1;
            int index = 0;
            int id = 0;
            //表头
            string title = "ID(数字必须唯一)";
            title += ",所属模块";
            title += ",名称";
            title += ",类型(0=直线1=旋转)";
            title += ",最大速度unit/s";
            title += ",最大加速度g rad/s";
            title += ",节距mm/rad";
            title += ",分辨率plus";
            title += ",回零方式coe402";
            title += ",回零快速";
            title += ",回零慢速";
            title += ",回零偏移unit";
            title += ",固高轴识别码";
            title += ",驱动器名称-读取绝对值的时候用";
            title += ",驱动器额外参数-读取绝对值的时候用";
            msg.Add(title);
            foreach (var item in cfg)
            {
                string txt = "";
                index = 0;
                foreach (var item2 in item.axisModelList)
                {
                    switch (item2)
                    {
                        case EGsnModelType.M40300:
                            for (int i = 0; i < 4; i++)
                            {
                                txt = "";
                                txt += id.ToString();
                                txt += "," + "轴" + index.ToString();
                                txt += ","+"0";
                            }
                            break;
                        case EGsnModelType.M60200:
                            break;
                        case EGsnModelType.M40200:
                            break;
                        case EGsnModelType.M40301:
                            break;
                    }
                }
                core++;
            }
            //保存
            try
            {
                FileStream stream = File.Create(csv);
                StreamWriter write = new StreamWriter(stream);
                foreach (var item in msg)
                {
                    write.WriteLine(item);
                }
                write.Close();
                write.Dispose();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 根据硬件配置表
        /// 导出用于客户编辑IO表的定义
        /// </summary>
        /// <param name="csv">输出文件名称</param>
        /// <returns></returns>
        public override bool exportIoToCsv(string csv)
        {
            List<string> msg = new List<string>();
            int core = 1;
            short distart = 0;
            short dostart = 0;
            short aistart = 0;
            short aostart = 0;
            //short encstart = 0;
            //short cmpstrat = 0;
            int iocounter = 1;
            long shibiema = 0;
            long duquqishi = 0;
            string txt = "";
            CIoModelPrm P = new CIoModelPrm();
            //表头
            msg.Add("模块名称,模块识别号XXXX_YYYY_ZZZZ,读取数据起始Index,\"全局ID(全部唯一, 用来映射)\",\"类型(输入, 输出, 模拟量输入, 模拟量输出，编码器, 比较输出)\",引脚号,名称,正常/取反");
            foreach (var item in cfg)
            {
                distart = 0;
                dostart = 0;
                P.clear();
                foreach (var item2 in item.axisModelList)
                {
                    switch (item2)
                    {
                        case EGsnModelType.M40300:
                            //构造一个模块参数
                            P.CardIDOrModelID = core;
                            P.ExtModelID = 0;
                            P.IsLocal = true;
                            shibiema = P.modelSign;
                            //设置一个启示读取码
                            P.DiStartIndex = distart;
                            P.DoStartIndex = dostart;
                            duquqishi = P.startIndexSign;
                            txt = "4轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 22; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                distart++;
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                dostart++;
                            }
                            break;
                        case EGsnModelType.M60200:
                            P.CardIDOrModelID = core;
                            txt = "6轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 16; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                distart++;
                                txt = ",,";
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                dostart++;
                                txt = ",,";
                            }
                            break;
                        case EGsnModelType.M40200:
                            P.CardIDOrModelID = core;
                            txt = "4轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 22; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                distart++;
                                txt = ",,";
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                dostart++;
                                txt = ",,";
                            }
                            break;
                        case EGsnModelType.M40301:
                            P.CardIDOrModelID = core;
                            txt = "4轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 22; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                distart++;
                                txt = ",,";
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                dostart++;
                                txt = ",,";
                            }
                            break;
                         case EGsnModelType.M4XX:
                            //构造一个模块参数
                            P.CardIDOrModelID = core;
                            P.ExtModelID = 0;
                            P.IsLocal = true;
                            shibiema = P.modelSign;
                            //设置一个启示读取码
                            P.DiStartIndex = distart;
                            P.DoStartIndex = dostart;
                            duquqishi = P.startIndexSign;
                            txt = "4轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 22; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                distart++;
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                dostart++;
                            }
                            break;
                        case EGsnModelType.M6XX:
                            P.CardIDOrModelID = core;
                            txt = "6轴模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 16; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "本地输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                distart++;
                                txt = ",,";
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 10; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "本地输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                dostart++;
                                txt = ",,";
                            }
                            break;
                    }
                }
                int exiID = 0;
                distart = 0;
                dostart = 0;
                aistart = 0;
                aostart = 0;
                P.clear();
                foreach (var item2 in item.extIoList)
                {
                    switch (item2.ioType)
                    {
                        case EGsnIoType.ACC1616D:
                            P.CardIDOrModelID = core;
                            P.ExtModelID = exiID;
                            P.IsLocal = false;
                            shibiema = P.modelSign;
                            //设置一个启示读取码
                            P.DiStartIndex = distart;
                            P.DoStartIndex = dostart;
                            duquqishi = P.startIndexSign;
                            txt = "16I16O扩展模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 16; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "扩展模块数字量输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                distart++;
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 16; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "扩展模块数字量输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                dostart++;
                            }
                            break;
                        case EGsnIoType.ACC0604A:
                            P.CardIDOrModelID = core;
                            P.ExtModelID = exiID;
                            P.IsLocal = false;
                            shibiema = P.modelSign;
                            //设置一个启示读取码
                            P.AiStartIndex = aistart;
                            P.AoStartIndex = aostart;
                            duquqishi = P.startIndexSign;
                            txt = "6AI4AO扩展模块";
                            txt += "," + shibiema.ToString();
                            txt += "," + duquqishi.ToString();
                            //本地输入
                            for (int i = 0; i < 6; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "模拟量输入";
                                txt += "," + "Exi" + i.ToString();
                                txt += "," + "扩展模块模拟量输入" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                aistart++;
                            }
                            //本地输出
                            txt = ",,";
                            for (int i = 0; i < 4; i++)
                            {
                                txt += "," + (iocounter++).ToString();
                                txt += "," + "模拟量输出";
                                txt += "," + "Ext" + i.ToString();
                                txt += "," + "扩展模块模拟量输出" + i.ToString();
                                txt += "," + "正常";
                                msg.Add(txt);
                                txt = ",,";
                                aostart++;
                            }
                            break;
                    }
                    exiID++;
                }
                core++;
            }
            //保存
            try
            {
                FileStream stream = File.Create(csv);
                StreamWriter write = new StreamWriter(stream);
                foreach (var item in msg)
                {
                    write.WriteLine(item);
                }
                write.Close();
                write.Dispose();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        public override bool importFromCsv(string csv)
        {
            return true;
        }
        /// <summary>
        /// 从XML中导入配置文件
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public override bool importFromXml(string xml)
        {
            //先读取类型
            XmlDocument doc = new XmlDocument();
            doc.Load(xml);
            XmlNodeList nds = doc.SelectNodes("/Hard/Hard");
            if (nds == null)
                return false;
            foreach (XmlNode item in nds)
            {
                CCfgDataGsn data = new CCfgDataGsn();
                foreach (XmlNode item2 in item.ChildNodes)
                {
                    switch (item2.Name)
                    {
                        case "initReset":
                            data.initreset = bool.Parse(item2.InnerText);
                            break;
                        case "uninitReset":
                            data.uninitReset = bool.Parse(item2.InnerText);
                            break;
                        case "ConfigeFile":
                            data.cardConfigeFn = item2.InnerText;
                            break;
                        case "AxisModel":
                            XmlNodeList tmp1Node = item2.ChildNodes;
                            foreach (XmlNode item3 in tmp1Node)
                            {
                                if (item3.InnerText == "40300")
                                {
                                    data.axisModelList.Add(EGsnModelType.M40300);
                                }
                                else if (item3.InnerText == "60200")
                                {
                                    data.axisModelList.Add(EGsnModelType.M60200);
                                }
                                else if (item3.InnerText == "40200")
                                {
                                    data.axisModelList.Add(EGsnModelType.M40200);
                                }
                                else if (item3.InnerText == "40301")
                                {
                                    data.axisModelList.Add(EGsnModelType.M40301);
                                }
                                else if (item3.InnerText.IndexOf("40") >=0)
                                {
                                    data.axisModelList.Add(EGsnModelType.M4XX);
                                }
                                else if(item3.InnerText.IndexOf("60") >= 0)
                                {
                                    data.axisModelList.Add(EGsnModelType.M6XX);
                                }
                            }
                            break;
                        case "CardType":
                            string cardTypeStr = item2.InnerText;
                            cardTypeStr = cardTypeStr.ToUpper();
                            if (cardTypeStr.IndexOf("V24") >= 0)
                            {
                                data.cardType = EGsnCardType.V24;
                            }
                            else if (cardTypeStr.IndexOf("G24") >= 0)
                            {
                                data.cardType = EGsnCardType.G24;
                            }
                            else if (cardTypeStr.IndexOf("G800") >= 0)
                            {
                                data.cardType = EGsnCardType.G800;
                            }
                            else if (cardTypeStr.IndexOf("V800") >= 0)
                            {
                                data.cardType = EGsnCardType.V800;
                            }
                            break;
                        case "IoModel":
                            if (item2.ChildNodes.Count > 0)
                            {
                                foreach (XmlNode item3 in item2.ChildNodes)
                                {
                                    switch (item3.Name)
                                    {
                                        case "ConfigeFile":
                                            data.extIoFn = item3.InnerText;
                                            break;
                                        case "Model":
                                            CCfgIoDataGsn io = new CCfgIoDataGsn();
                                            string id = item3.Attributes["id"].Value;
                                            io.id = int.Parse(id);
                                            string ioTypeStr = item3.InnerText.ToUpper();
                                            if (ioTypeStr.IndexOf("1616") >= 0)
                                            {
                                                io.ioType = EGsnIoType.ACC1616D;
                                            }
                                            else if (ioTypeStr.IndexOf("0604") >= 0)
                                            {
                                                io.ioType = EGsnIoType.ACC0604A;
                                            }
                                            data.extIoList.Add(io);
                                            break;
                                    }
                                }
                            }
                            break;
                    }
                }
                cfg.Add(data);
            }
            return true;
        }
    }
    /// <summary>
    /// 用户定义的会与啊你单
    /// </summary>
    public class CUserDefineHome
    {
        Thread td = null;
        int step = 0;
        bool canrun = false;
        IMotionPartI p1 = null;
        CAxisRef axis = null;
        private void HomeFun()
        {
            canrun = true;
            while (canrun)
            {
                switch (step)
                {
                    case 1:
                        break;
                    default:
                        break;
                }
                Thread.Sleep(5);
            }
        }
        public void start(CAxisRef axis,IMotionPartI p1)
        {
            this.axis = axis;
            this.p1 = p1;
            if(td != null && td.IsAlive)
            {
                td.Abort();
                td = null;
            }
            td = new Thread(HomeFun);
            td.IsBackground = true;
            td.Start();
        }
        public void stop()
        {

        }
    }
    public class CMotionCard_GSN:IInitModel,IMotionPartI,IIoPart,IMotionPartII,IMotionPartSpecial
    {
        private CCfgGsn cfg = null;
        public bool initOk = false;

        private Thread runThread = null;//用来刷新IO的
        private uint clock = 0;
        //私有变量
        private short cardNum = 0;
        public CMotionCard_GSN(CCfgGsn cfg)
        {
            this.cfg = cfg;
        }
        public void Fresh()
        {

        }
        public void setDangliang()
        {
            short rtn = mc.GTN_SetProfileScale(1, 3, 200, 1250);
        }
        public void test()
        {
            mc.TTrapPrm p = new mc.TTrapPrm();
            p.acc = p.dec = 1;
            mc.GTN_SetPos(1, 3, 100);
            mc.GTN_SetTrapPrm(1, 3, ref p);
            mc.GTN_SetVel(1, 3, 10);
            mc.GTN_Update(1, 4);
            double prfpos = 0;
            double axisprfpos = 0;
            uint clock = 0;
            mc.GTN_GetPrfPos(1, 3, out prfpos, 1, out clock);
            mc.GTN_GetAxisPrfPos(1, 3, out axisprfpos, 1, out clock);
        }
        public bool Init()
        {
            try
            {
                short rtn = 0;
                initOk = false;
                cardNum = 1;
                if (cfg.cfg.Count == 0)
                    return false;
                rtn = mc.GTN_Open(5, 2);
                if (rtn != 0)
                    return false;
                foreach (CCfgDataGsn item in cfg.cfg)
                {
                    if (item.initreset)
                        rtn += mc.GTN_Reset(cardNum);
                    rtn += mc.GTN_LoadConfig(cardNum, item.cardConfigeFn);
                    switch (item.cardType)
                    {
                        case EGsnCardType.G24:
                            rtn += mc.GTN_ClrSts(cardNum, 1, 24); 
                            if (item.initreset)
                                rtn += mc.GTN_ZeroPos(cardNum, 1, 24);
                            break;
                        case EGsnCardType.V24:
                            rtn += mc.GTN_ClrSts(cardNum, 1, 24);
                            if (item.initreset)
                                rtn += mc.GTN_ZeroPos(cardNum, 1, 24);
                            break;
                        case EGsnCardType.G800:
                            rtn += mc.GTN_ClrSts(cardNum, 1, 8);
                            if (item.initreset)
                                rtn += mc.GTN_ZeroPos(cardNum, 1, 8);
                            break;
                        case EGsnCardType.V800:
                            rtn += mc.GTN_ClrSts(cardNum, 1, 8);
                            if (item.initreset)
                                rtn += mc.GTN_ZeroPos(cardNum, 1, 8);
                            break;
                    }
                    //有IO模块 TODO:
                    if (item.extIoFn != "")
                    {
                        //rtn += mc.GTN_ExtModuleInit(cardNum, "gts");
                        //rtn += mc.GTN_ResetExtMdl(cardNum);
                        //rtn += mc.GTN_LoadExtConfig(cardNum, item.extIoFn);
                    }
                    cardNum++;
                }
                //if (rtn == 0)
                //{
                //    runThread = new System.Threading.Thread(Run);
                //    runThread.IsBackground = true;
                //    runThread.Start();
                //    return initOk = true;
                //}
                return initOk = (rtn == 0);
            }
            catch (Exception e)
            {
                string errStr = e.Message;
                return initOk = false;
            }
        }

        public bool UnInit()
        {
            try
            {
                short rtn = 0;
                short cardNum = 0;
                foreach (CCfgDataGsn item in cfg.cfg)
                {
                    //有IO模块
                    if (item.extIoFn != "")
                    {
                        //rtn += mc.GT_ResetExtMdl(cardNum);
                        //rtn += mc.GT_CloseExtMdl(cardNum);
                    }
                    //关闭卡
                    if (item.uninitReset)
                        rtn += mc.GTN_Reset(cardNum);
                    cardNum++;
                }
                rtn += mc.GTN_Close();
                //停止刷新
                if (runThread != null && runThread.IsAlive)
                {
                    runThread.Abort();
                    Thread.Sleep(5);
                    runThread = null;
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        public int MC_AxisRef(ref CAxisRef axisref)
        {
            int sts = 0;
            uint clock = 0;
            double prfpos = 0, encpos = 0, encvel = 0,poserr = 0;
            int homeswitch = 0,lmtpswitch = 0,lmtnswitch = 0;
            short rtn = 0;
            rtn += mc.GTN_GetSts(axisref.prm.cardNum, axisref.prm.axisNum, out sts, 1, out clock);
            rtn += mc.GTN_GetPrfPos(axisref.prm.cardNum, axisref.prm.axisNum, out prfpos, 1, out clock);
            rtn += mc.GTN_GetEncPos(axisref.prm.cardNum, axisref.prm.axisNum, out encpos, 1, out clock);
            rtn += mc.GTN_GetEncVel(axisref.prm.cardNum, axisref.prm.axisNum, out encvel, 1, out clock);
            rtn += mc.GTN_GetAxisError(axisref.prm.cardNum, axisref.prm.axisNum, out poserr, 1, out clock);
            rtn += mc.GTN_GetDi(axisref.prm.cardNum, mc.MC_HOME, out homeswitch);
            rtn += mc.GTN_GetDi(axisref.prm.cardNum, mc.MC_LIMIT_POSITIVE, out lmtpswitch);
            rtn += mc.GTN_GetDi(axisref.prm.cardNum, mc.MC_LIMIT_NEGATIVE, out lmtnswitch);
            axisref.swHome = ((1 << (axisref.prm.axisNum - 1)) & homeswitch) == 0;
            axisref.swLmtP = ((1 << (axisref.prm.axisNum - 1)) & lmtpswitch) == 0;
            axisref.swLmtN = ((1 << (axisref.prm.axisNum - 1)) & lmtnswitch) == 0;
            axisref.alarm = (sts & 0x2) != 0;
            axisref.servoOn = (sts & 0x200) != 0;
            axisref.limitN = (sts & 0x40) != 0;
            axisref.limitP = (sts & 0x20) != 0;
            axisref.moving = (sts & 0x400) != 0;
            axisref.followPos = poserr;
            axisref.cmdPos = axisref.prm.pls2mm(prfpos) * axisref.prm.cmdDangliang;
            axisref.relPos = axisref.prm.pls2mm(encpos)*axisref.prm.encDangliang;
            axisref.relVel = axisref.prm.plsperms2mmpers(encvel);
            return rtn;
        }

        public int MC_EStop(CAxisRef axis)
        {
            axis.isHoming = false;
            mc.GTN_Stop(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1), 1 << (axis.prm.axisNum - 1));
            return 0;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="axis"></param>
        /// <returns>-1000=绝对值读取位NULL</returns>
        public int MC_Home(ref CAxisRef axis)
        {
            //如果这个线程还在,先停止
            if (axis.homeTask != null && axis.homeTask.Status == TaskStatus.Running)
            {
                axis.cancelHome = true;
                while (axis.homeTask.Status == TaskStatus.Running)
                {
                    Thread.Sleep(5);
                }
                axis.homeTask = null;
            }
            //判断回零方式了
            if (axis.prm.homeType >= 1000)
            {
                if (axis.prm.homeType == 1000)
                {
                    if (axis.prm.AbsReader == null)
                    {
                        if (axis.prm.driverTypeName.ToUpper() == "COPLEY")
                        {
                            CCopleyAbcEnc rd = new CCopleyAbcEnc(axis.prm.driverPrmString);
                            axis.prm.AbsReader = rd;
                        }
                    }
                    axis.homed = 0;
                    axis.isHoming = true;
                    if (axis.prm.AbsReader.read(ref axis) == 0)
                    {
                        axis.homed = 1; 
                        axis.isHoming = false;
                        double relpos = 0;
                        if (axis.prm.absEncDirect > 0)
                        {
                            relpos = axis.prm.pls2mm((axis.prm.absEncPosByRead - axis.prm.absEncZeroPos)* axis.prm.absEnc2AddRate);
                        }
                        else
                        {
                            relpos = axis.prm.pls2mm((-axis.prm.absEncPosByRead + axis.prm.absEncZeroPos) * axis.prm.absEnc2AddRate);
                        }
                        MC_SetPos(axis,relpos);
                    }
                    else
                    {
                        axis.homed = -1;
                        axis.isHoming = false;
                    }
                }
                return -1;
            }
            else if (axis.prm.homeType >= 500)//自定义回零-这里暂时不做任何动作
            {
                CAxisRef a = axis;
                a.cancelHome = false;
                a.isHoming = true;
                a.homed = 0;
                axis.homeTask = new Task(async () =>
                {
                    int step = 1;
                    int rtn = 0;
                    CDelay homeDelay = new CDelay();
                    mc.TTriggerEx triger = new mc.TTriggerEx();
                    mc.TTriggerStatusEx trigerSts = new mc.TTriggerStatusEx();
                    while (!a.cancelHome && step != 0)
                    {
                        MC_AxisRef(ref a);
                        switch (step)
                        {
                            case 1:
                                MC_SetPos(a, 0);
                                rtn = GSN.mc.GTN_GetTriggerEx(a.prm.cardNum, a.prm.axisNum, out triger);
                                triger.latchType = GSN.mc.MC_ENCODER;
                                triger.latchIndex = a.prm.axisNum;
                                triger.firstPosition = 0;
                                triger.lastPosition = 0;
                                triger.loop = 1;
                                triger.offset = 0;
                                triger.probeIndex = a.prm.axisNum;
                                triger.probeType = GSN.mc.CAPTURE_HOME;
                                if (a.prm.homeTriger > 0)
                                {
                                    triger.sense = 1;
                                }
                                else
                                {
                                    triger.sense = 0;
                                }
                                triger.windowOnly = 0;
                                rtn += GSN.mc.GTN_SetTriggerEx(a.prm.cardNum, a.prm.axisNum, ref triger);
                                rtn += MC_MoveAbs(a, a.prm.homeSearch, a.prm.homeVel1 / a.prm.maxVel);
                                if (rtn != 0)
                                {
                                    step = 0;
                                    a.isHoming = false;
                                    break;
                                }
                                step = 4;
                                break;
                            case 4:
                                rtn = GSN.mc.GTN_GetTriggerStatusEx(a.prm.cardNum, a.prm.axisNum, out trigerSts, 1);
                                if (trigerSts.done == 1)
                                {
                                    MC_EStop(a);
                                    step = 5;
                                }
                                else
                                {
                                    if (a.limitP)
                                    {
                                        rtn = MC_MoveAdd(a, -a.prm.homeLeave, a.prm.homeVel1 / a.prm.maxVel);
                                        homeDelay.SetTime(100);
                                        step = 7;
                                    }
                                    else if (a.limitN)
                                    {
                                        rtn = MC_MoveAdd(a, a.prm.homeLeave, a.prm.homeVel1 / a.prm.maxVel);
                                        homeDelay.SetTime(100);
                                        step = 7;
                                    }
                                }
                                break;
                            case 5:
                                if (a.moving)
                                    break;
                                double trigerpos = a.prm.pls2mm(trigerSts.position) * a.prm.encDangliang + a.prm.homeoffset;
                                MC_MoveAbs(a, trigerpos, a.prm.homeVel1 / a.prm.maxVel);
                                step = 6;
                                break;
                            case 6:
                                if (a.moving)
                                    break;
                                double setpos = a.prm.homeoffsetSet;
                                MC_SetPos(a, setpos);
                                if (Math.Abs(a.prm.homeOverMoveAddtion) >0.0001)
                                {
                                    MC_Reset(a);
                                    MC_MoveAdd(a, a.prm.homeOverMoveAddtion, a.prm.homeVel1 / a.prm.maxVel);
                                    step = 8;
                                }
                                else
                                {
                                    homeDelay.SetTime(500);
                                    step = 100;
                                }
                                break;
                            case 7:
                                if (a.moving)
                                    break;
                                MC_Reset(a);
                                MC_SetPos(a, 0);
                                step = 1;
                                break;
                            case 8:
                                if (a.moving)
                                    break;
                                homeDelay.SetTime(500);
                                step = 100;
                                break;
                            case 100:
                                if (homeDelay.TimeOut)
                                {
                                    MC_SetPos(a, a.prm.homeoffsetSet);
                                    a.homed = 1;
                                    a.isHoming = false;
                                    step = 0;
                                }
                                break;
                        }
                        await Task.Delay(5);
                    }
                }
                );
                axis.homeTask.Start();
                return 0;
            }
            else if (axis.prm.homeType == -1)
            {
                MC_SetPos(axis, 0);
                axis.homed = 1;
                axis.isHoming = false;
                return 0;
            }
            else
            {
                short rtn = 0;
                rtn = mc.GTN_ZeroPos(axis.prm.cardNum, axis.prm.axisNum, 1);
                mc.THomePrm prm = new mc.THomePrm();
                axis.homed = 0;
                axis.isHoming = false;
                rtn = mc.GTN_GetHomePrm(axis.prm.cardNum, axis.prm.axisNum, out prm);
                rtn = mc.GTN_ClrSts(axis.prm.cardNum, axis.prm.axisNum, 1);
                prm.mode = axis.prm.homeType;
                prm.acc = axis.prm.getAccPlsPerMs2();
                prm.dec = prm.acc;
                if (axis.prm.homeSearch >= 0)
                {
                    prm.moveDir = 1;
                }
                else
                {
                    prm.moveDir = -1;
                }
                prm.indexDir = 1;
                prm.edge = (short)axis.prm.homeTriger;
                prm.homeOffset = (int)axis.prm.mm2pls(axis.prm.homeoffset);
                double vel = axis.prm.mmpers2plsperms(axis.prm.homeVel1);
                prm.velHigh = axis.prm.mmpers2plsperms(axis.prm.homeVel1);
                prm.velLow = axis.prm.mmpers2plsperms(axis.prm.homeVel2);
                //苏索距离都用0 表示无线搜索
                prm.searchHomeDistance = 0;// Math.Abs((int)axis.prm.mm2pls(axis.prm.homeSearch));
                prm.searchIndexDistance = 0;// prm.searchHomeDistance;
                prm.escapeStep = (int)axis.prm.mm2pls(axis.prm.homeLeave);
                rtn += mc.GTN_GoHome(axis.prm.cardNum, axis.prm.axisNum, ref prm);
                //启动异步判断
                CAxisRef axis2 = axis;
                axis2.cancelHome =false;
                if (rtn == 0)
                {
                    axis.isHoming = true;
                    axis.homeTask = new Task(async () =>
                    {
                        int step = 1;
                        CDelay delay = new CDelay();
                        while (!axis2.cancelHome && step != 0)
                        {
                            MC_AxisRef(ref axis2);
                            switch (step)
                            {
                                case 1:
                                    MC_HomeStatus(ref axis2);
                                    if (!axis2.isHoming)
                                    {
                                        if (axis2.homed == 1)
                                        {
                                            step = 10;
                                        }
                                        else if (axis2.homed == -1)
                                        {
                                            step = 200;
                                        }
                                    }
                                    break;
                                case 10:
                                    MC_SetPos(axis2, axis2.prm.homeoffsetSet);
                                    if (Math.Abs(axis2.prm.homeOverMoveAddtion) > 0.0001)
                                    {
                                        MC_Reset(axis2);
                                        MC_MoveAdd(axis2, axis2.prm.homeOverMoveAddtion, axis2.prm.homeVel1 / axis2.prm.maxVel);
                                        step = 20;
                                    }
                                    else
                                    {
                                        delay.SetTime(500);
                                        step = 100;
                                    }
                                    break;
                                case 20:
                                    if (axis2.moving)
                                        break;
                                    delay.SetTime(500);
                                    step = 100;
                                    break;
                                case 100:
                                    if (delay.TimeOut)
                                    {
                                        MC_SetPos(axis2, axis2.prm.homeoffsetSet);
                                        axis2.homed = 1;
                                        axis2.isHoming = false;
                                        step = 0;
                                    }
                                    break;
                                case 200:
                                    axis2.homed = 0;
                                    axis2.isHoming = false;
                                    step = 0;
                                    break;
                            }
                            await Task.Delay(5);
                        }
                    }
                    );
                    axis.homeTask.Start();
                }
                else
                {
                    axis.isHoming = false;
                }
                return rtn;
            }
        }

        public int MC_HomeStatus(ref CAxisRef axis)
        {
            short rtn = 0;
            if (axis.prm.homeType >= 1000)//内部更新回零状态
            {

            }
            else if (axis.prm.homeType >= 500)//内部更新回零状态
            {

            }
            else if (axis.prm.homeType == -1)//内部更新回零状态
            {

            }
            else
            {
                if (axis.isHoming)
                {
                    mc.THomeStatus tmpHomeSts = new mc.THomeStatus();
                    rtn = mc.GTN_GetHomeStatus(axis.prm.cardNum, axis.prm.axisNum, out tmpHomeSts);
                    if (rtn == 0)
                    {
                        if (tmpHomeSts.run == 0 && tmpHomeSts.error == mc.HOME_ERROR_NONE)//回零完成
                        {
                            axis.homed = 1;
                            //mc.GTN_ZeroPos(axis.prm.cardNum, axis.prm.axisNum, 1);
                            axis.isHoming = false;
                        }
                        if (tmpHomeSts.run == 0 && tmpHomeSts.error != mc.HOME_ERROR_NONE)//回零完成
                        {
                            axis.homed = -1;
                            axis.isHoming = false;
                        }
                    }
                    return rtn;
                }
            }
            
            return 0;
        }

        public int MC_MoveAbs(CAxisRef axis, double tpos, double beilv = 0.5)
        {
            short rtn = 0;
            int pmode;
            int psts;
            uint pclock;
            rtn += mc.GTN_GetPrfMode(axis.prm.cardNum, axis.prm.axisNum, out pmode, 1, out pclock);
            rtn += mc.GTN_GetSts(axis.prm.cardNum, axis.prm.axisNum, out psts, 1, out pclock);
            var p = axis.prm;
            if (axis.prm.enableSoftlmt >0 && !axis.isHoming)
            {
                if (tpos > p.softlmtp || tpos < p.softlmtn)
                {
                    return -100;
                }
            }
            if ((psts & 0x400) == 0)
            {
                if (pmode != 0)
                {
                    rtn += mc.GTN_PrfTrap(axis.prm.cardNum, axis.prm.axisNum);
                }
                mc.TTrapPrm trapprm = new mc.TTrapPrm();
                trapprm.acc = axis.prm.getAccPlsPerMs2();
                trapprm.dec = axis.prm.getDecPlsPerMs2();
                trapprm.smoothTime = 0;
                trapprm.velStart = 0;
                rtn += mc.GTN_SetTrapPrm(axis.prm.cardNum, axis.prm.axisNum, ref trapprm);
                rtn += mc.GTN_SetVel(axis.prm.cardNum, axis.prm.axisNum, axis.prm.getVelPlsPerMs() * beilv);
                rtn += mc.GTN_SetPos(axis.prm.cardNum, axis.prm.axisNum, (int)(axis.prm.mm2pls(tpos)));
                //int sts = 0;
                //uint clock = 0;
                //rtn = mc.GT_GetSts(cardnum, relAxis, out sts, 1, out clock);
                rtn += mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            }
            else if (pmode == 0)
            {
                rtn += mc.GTN_SetVel(axis.prm.cardNum, axis.prm.axisNum, axis.prm.getVelPlsPerMs() * beilv);
                rtn += mc.GTN_SetPos(axis.prm.cardNum, axis.prm.axisNum, (int)(axis.prm.mm2pls(tpos)));
                rtn += mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            }
            return rtn;
        }

        public int MC_MoveAdd(CAxisRef axis, double dist, double beilv = 0.5)
        {
            short rtn = 0;
            int pmode, psts;
            uint pclock;
            double prfpos;
            rtn += mc.GTN_GetSts(axis.prm.cardNum, axis.prm.axisNum, out psts, 1, out pclock);
            var p = axis.prm;
            if (p.enableSoftlmt > 0 && !axis.isHoming)
            {
                mc.GTN_GetPrfPos(axis.prm.cardNum, axis.prm.axisNum, out prfpos, 1, out pclock);
                double tpos = p.pls2mm(prfpos) + dist;
                if (tpos > p.softlmtp || tpos < p.softlmtn)
                {
                    return -100;
                }
            }
            if ((psts & 0x400) == 0)
            {
                rtn += mc.GTN_GetPrfMode(axis.prm.cardNum, axis.prm.axisNum, out pmode, 1, out pclock);
                if (pmode != 0)
                    rtn += mc.GTN_PrfTrap(axis.prm.cardNum, axis.prm.axisNum);
                mc.TTrapPrm trapprm = new mc.TTrapPrm();
                trapprm.acc = axis.prm.getAccPlsPerMs2();
                trapprm.dec = axis.prm.getDecPlsPerMs2();
                trapprm.smoothTime = 0;
                trapprm.velStart = 0;
                rtn += mc.GTN_SetTrapPrm(axis.prm.cardNum, axis.prm.axisNum, ref trapprm);
                rtn += mc.GTN_SetVel(axis.prm.cardNum, axis.prm.axisNum, axis.prm.getVelPlsPerMs() * beilv);
                rtn += mc.GTN_GetPrfPos(axis.prm.cardNum, axis.prm.axisNum, out prfpos, 1, out pclock);
                rtn += mc.GTN_SetPos(axis.prm.cardNum, axis.prm.axisNum, (int)(axis.prm.mm2pls(dist) + prfpos));
                rtn += mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            }
            else
            {
                rtn += mc.GTN_GetPrfMode(axis.prm.cardNum, axis.prm.axisNum, out pmode, 1, out pclock);
                if (pmode == 0)
                {
                    rtn += mc.GTN_GetPrfPos(axis.prm.cardNum, axis.prm.axisNum, out prfpos, 1, out pclock);
                    rtn += mc.GTN_SetPos(axis.prm.cardNum, axis.prm.axisNum, (int)(axis.prm.mm2pls(dist) + prfpos));
                    rtn += mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
                }
            }
            return rtn;
        }

        public int MC_MoveJog(CAxisRef axis, double beilv = 0.5)
        {
            try
            {
                short rtn = 0;
                int pmode;
                int psts;
                uint pclock;
                rtn += mc.GTN_GetPrfMode(axis.prm.cardNum, axis.prm.axisNum, out pmode, 1, out pclock);
                rtn += mc.GTN_GetSts(axis.prm.cardNum, axis.prm.axisNum, out psts, 1, out pclock);
                if ((psts & 0x400) == 0)
                {
                    if (pmode != 1)
                        rtn = mc.GTN_PrfJog(axis.prm.cardNum, axis.prm.axisNum);
                    mc.TJogPrm jogprm = new mc.TJogPrm();
                    jogprm.acc = axis.prm.getAccPlsPerMs2();
                    jogprm.dec = axis.prm.getDecPlsPerMs2();
                    jogprm.smooth = 0.5;
                    rtn = mc.GTN_SetJogPrm(axis.prm.cardNum, axis.prm.axisNum, ref jogprm);
                    rtn = mc.GTN_SetVel(axis.prm.cardNum, axis.prm.axisNum, axis.prm.getVelPlsPerMs() * beilv);
                    rtn = mc.GTN_ClrSts(axis.prm.cardNum, axis.prm.axisNum, 1);
                    rtn = mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
                }
                else if (pmode == 1)
                {
                    rtn = mc.GTN_SetVel(axis.prm.cardNum, axis.prm.axisNum, axis.prm.getVelPlsPerMs() * beilv);
                    rtn = mc.GTN_ClrSts(axis.prm.cardNum, axis.prm.axisNum, 1);
                    rtn = mc.GTN_Update(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
                }
                return rtn;
            }
            catch (Exception)
            {
                return -1;
            }
        }


        public int MC_PowerOff(CAxisRef axis)
        {
            short rtn = 0;
            rtn += mc.GTN_AxisOff(axis.prm.cardNum, axis.prm.axisNum);
            return rtn;
        }

        public int MC_Reset(CAxisRef axis)
        {
            mc.GTN_ClrSts(axis.prm.cardNum, axis.prm.axisNum, 1);
            MC_AxisRef(ref axis);
            if (axis.alarm)
            {
                mc.GTN_SetDoBitReverse(axis.prm.cardNum, axis.prm.axisNum, mc.MC_CLEAR, axis.prm.axisNum, 1000);
            }
            return 0;
        }


        public int MC_SetPos(CAxisRef axis, double pos)
        {
            short rtn = 0;
            int tpos = (int)axis.prm.mm2pls(pos);
            rtn += mc.GTN_SetPrfPos(axis.prm.cardNum, axis.prm.axisNum, tpos);
            rtn += mc.GTN_SetEncPos(axis.prm.cardNum, axis.prm.axisNum, tpos);
            rtn += mc.GTN_SynchAxisPos(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            return rtn;
        }
        

        public void Run()
        {

        }
        

        public int MC_PowerOn(CAxisRef axis)
        {
            short rtn = 0;
            int sts = 0;
            uint clock = 0;
            rtn += mc.GTN_ClrSts(axis.prm.cardNum, axis.prm.axisNum, 1);
            rtn += mc.GTN_GetSts(axis.prm.cardNum, axis.prm.axisNum, out sts,1,out clock);
            if ((sts & 0x2) != 0)
                return 1;
            double pos = 0;
            if (axis.prm.closeLoop > 0)
            {
                mc.TPid pid = new mc.TPid();
                rtn += mc.GTN_GetPid(axis.prm.cardNum, axis.prm.axisNum, 1, out pid);
                pid.kp = axis.prm.kp;
                pid.ki = axis.prm.ki;//强制为0 这东西容易飞车
                pid.kd = axis.prm.kd;
                pid.kaff = axis.prm.kaff;
                pid.kvff = axis.prm.kvff;
                pid.IntegralLimit = (int)axis.prm.kilmt;
                rtn += mc.GTN_SetPid(axis.prm.cardNum, axis.prm.axisNum, 1, ref pid);
            }
            rtn += mc.GTN_SynchAxisPos(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            rtn += mc.GTN_AxisOn(axis.prm.cardNum, axis.prm.axisNum);
            rtn += mc.GTN_GetEncPos(axis.prm.cardNum, axis.prm.axisNum, out pos, 1, out clock);
            double relpos = axis.prm.pls2mm(pos) * axis.prm.encDangliang;
            double targetPrfpos = axis.prm.mm2pls(relpos);
            rtn += mc.GTN_SetPrfPos(axis.prm.cardNum, axis.prm.axisNum, (int)targetPrfpos);
            rtn += mc.GTN_SynchAxisPos(axis.prm.cardNum, 1 << (axis.prm.axisNum - 1));
            return rtn;
        }

        public int MC_SetAxisParameter(CAxisSinglePrm axisPrm)
        {
            return 0;
        }



        public int MC_CrdStatus(ref CCrdPrmSingle crd)
        {
            //mc.GTN_CrdStatus(crd.core,crd.crdNum,)
            return 0;
        }

        public int MC_CrdStart(string crdID)
        {
            CCrdPrmSingle crd = CGlbMc.crdPrm.get(crdID);
            if (crd == null)
                return 1;
            short rtn = mc.GTN_CrdStart((short)crd.core, (short)(1 << (crd.crdNum - 1)), 0);
            return rtn;
        }
        /// <summary>
        /// 执行G代码
        /// </summary>
        /// <param name="crdID"></param>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public int MC_CrdData(string crdID, string cmd)
        {
            if (MC_CrdCheckExist(crdID) ==0)
            {
                if (MC_CrdCreate(crdID) != 0)
                    return 1;
            }

            CCrdPrmSingle p = CGlbMc.crdPrm.get(crdID);
            //放入数据
            CGBase c = CGBase.createClass(cmd);
            if (c == null)
                return -1;
            short rtn = 0;

            //int alpha, beta;
            //uint clock2;
            //GTN.mc.GTN_SetProfileScale(1, 3, 200, 1250);
            //double[] pos = new double[10];
            //mc.GTN_GetPrfPos(1, 1, out pos[0], 5, out clock2);
            //rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, 1000, 1000, 1000, 0, 0, 1, 1, 0, 0);
            //if (rtn != 0)
            //    return rtn;

            int px=0, py=0, pz=0, pa=0, pb=0, pc=0;
            double synvel = 0;
            double synacc = 0;
            if (c is CG00)
            {
                CG00 g0 = c as CG00;
                var pt = g0.ept;
                double prfpos = 0;
                uint clock = 0;
                mc.GTN_SetG0Mode((short)p.core, (short)p.crdNum, 0);
                if (p.Dimension == 2)
                {
                    if (pt.x !=  double.MaxValue)
                    {
                        px = (int)p.tranPos("x", g0.ept.x);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                        px = (int)prfpos;
                    }
                    if (pt.y != double.MaxValue)
                    {
                        py = (int)p.tranPos("y", g0.ept.y);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                        py = (int)prfpos;
                    }
                    rtn += mc.GTN_LnXYG0((short)p.core, (short)p.crdNum, px, py, p.tranCrdVel(g0.cutVel), p.tranCrdAcc(), 0);
                }
                else if (p.Dimension == 3)
                {
                    if (pt.x != double.MaxValue)
                    {
                        px = (int)p.tranPos("x", g0.ept.x);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                        px = (int)prfpos;
                    }
                    if (pt.y != double.MaxValue)
                    {
                        py = (int)p.tranPos("y", g0.ept.y);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                        py = (int)prfpos;
                    }
                    if (pt.z != double.MaxValue)
                    {
                        pz = (int)p.tranPos("z", g0.ept.z);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[2], out prfpos, 1, out clock);
                        pz = (int)prfpos;
                    }
                    rtn += mc.GTN_LnXYZG0((short)p.core, (short)p.crdNum, px, py, pz, p.tranCrdVel(g0.cutVel), p.tranCrdAcc(), 0);
                }
                else if (p.Dimension == 4)
                {
                    if (pt.x != double.MaxValue)
                    {
                        px = (int)p.tranPos("x", g0.ept.x);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                        px = (int)prfpos;
                    }
                    if (pt.y != double.MaxValue)
                    {
                        py = (int)p.tranPos("y", g0.ept.y);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                        py = (int)prfpos;
                    }
                    if (pt.z != double.MaxValue)
                    {
                        pz = (int)p.tranPos("z", g0.ept.z);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[2], out prfpos, 1, out clock);
                        pz = (int)prfpos;
                    }
                    if (pt.a != double.MaxValue)
                    {
                        pa = (int)p.tranPos("a", g0.ept.a);
                    }
                    else
                    {
                        rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[3], out prfpos, 1, out clock);
                        pa = (int)prfpos;
                    }
                    rtn += mc.GTN_LnXYZAG0((short)p.core, (short)p.crdNum, px, py, pz, pa, p.tranCrdVel(g0.cutVel), p.tranCrdAcc(), 0);
                }
                if (rtn != 0)
                    return rtn;
            }
            else if (c is CG01)
            {
                CG01 g01 = c as CG01;
                if (Math.Abs(g01.A) > 0.0000001)
                {
                    rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], (int)p.tranPos("a", g01.A), 0);
                }
                if (Math.Abs(g01.B) > 0.0000001)
                {
                    rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], (int)p.tranPos("b", g01.B), 0);
                }
                if (g01.usedAxis == 3)
                {
                    px = (int)p.tranPos("x", g01.ept.x);
                    py = (int)p.tranPos("y", g01.ept.y);
                    
                    rtn += mc.GTN_LnXY((short)p.core, (short)p.crdNum, px,py , p.tranCrdVel(g01.cutVel), p.tranCrdAcc(), 0, 0);
                }
                else if (g01.usedAxis == 7)
                {
                    rtn += mc.GTN_LnXYZ((short)p.core, (short)p.crdNum, (int)p.tranPos("x", g01.ept.x), (int)p.tranPos("y", g01.ept.y), (int)p.tranPos("z", g01.ept.z),p.tranCrdVel(g01.cutVel), p.tranCrdAcc(), 0, 0);
                }
                if (rtn != 0)
                    return rtn;
            }
            else if (c is CG02)
            {
                CG02 a02 = c as CG02;
                if (Math.Abs(a02.A) > 0.0000001)
                {
                    mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], (int)p.tranPos("a", a02.A), 0);
                }
                if (Math.Abs(a02.B) > 0.0000001)
                {
                    rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], (int)p.tranPos("b", a02.B), 0);
                }
                //int alpha, beta;
                //GTN.mc.GTN_GetProfileScale(1, 3, out alpha, out beta);
                int x = (int)p.tranPos("x", a02.ept.x);
                int y = (int)p.tranPos("y", a02.ept.y);
                int i = (int)p.tranPos("x", a02.I);
                int j = (int)p.tranPos("y", a02.J);
                double[] prfpos = new double[8];
                mc.GTN_GetPrfPos(1, 1, out prfpos[0], 8, out clock);
                rtn = mc.GTN_SetArcAllowError((short)p.core, (short)p.crdNum, 2000);
                rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, x,y,i,j,(short)a02.direct,p.tranCrdVel(a02.cutVel), p.tranCrdAcc(), 0, 0);
               // rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, (int)p.tranPos("x", a02.ept.x), (int)p.tranPos("y", a02.ept.y), p.tranPos("x", a02.I), p.tranPos("y", a02.J), (short)a02.direct, p.tranCrdVel(a02.cutVel), p.tranCrdAcc(), 0, 0);

                if (rtn != 0)
                    return rtn;
            }
            else if (c is CG03)
            {
                CG03 a03 = c as CG03;
                if (Math.Abs(a03.A) > 0.0000001)
                {
                    mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], (int)p.tranPos("a", a03.A), 0);
                }
                if (Math.Abs(a03.B) > 0.0000001)
                {
                    rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], (int)p.tranPos("b", a03.B), 0);
                }
                int x = (int)p.tranPos("x", a03.ept.x);
                int y = (int)p.tranPos("y", a03.ept.y);
                int i = (int)p.tranPos("x", a03.I);
                int j = (int)p.tranPos("y", a03.J);
                double[] prfpos = new double[8];
                rtn = mc.GTN_SetArcAllowError((short)p.core, (short)p.crdNum, 2000);
                rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, (int)p.tranPos("x", a03.ept.x), (int)p.tranPos("y", a03.ept.y), p.tranPos("x", a03.I), p.tranPos("y", a03.J), (short)a03.direct, p.tranCrdVel(a03.cutVel), p.tranCrdAcc(), 0, 0);
                if (rtn != 0)
                    return rtn;
            }
            else if (c is CCmdCircle)
            {
                CCmdCircle circle = c as CCmdCircle;
                if (Math.Abs(circle.A) > 0.0000001)
                {
                    mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], (int)p.tranPos("a", circle.A), 0);
                }
                if (circle.B != 0)
                {
                    mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], (int)p.tranPos("b", circle.B), 0);
                }
                rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, (int)p.tranPos("x", circle.spt.x), (int)p.tranPos("y", circle.spt.y), p.tranPos("x", circle.I), p.tranPos("y", circle.J), (short)circle.direct, p.tranCrdVel(circle.cutVel), p.tranCrdAcc(), 0, 0);
                if (rtn != 0)
                    return rtn;
            }
            //启动
            //int space = 0;
            //mc.GTN_CrdSpace((short)p.core, (short)p.crdNum, out space, 0);
            int rst = MC_CrdStart(crdID);
            return rst;
        }
        /// <summary>
        /// TODO:需要测试
        /// </summary>
        /// <param name="crdID"></param>
        /// <param name="gcode"></param>
        /// <returns></returns>
        public int MC_CrdData(string crdID, List<string> gcode)
        {
            if (MC_CrdCreate(crdID) != 0)
                return 1;
            CCrdPrmSingle p = CGlbMc.crdPrm.get(crdID);
            //放入数据--非标行业 暂时不考虑太多数据的情况
            if (gcode.Count > 4096)
                return 2;
            short cmdCounter = 0;
            short rtn = 0;
            string cmd = "";
            bool isStart = false;
            int startSeg = p.startSeg;//多少段开始启动
            int pxnow = 0, pynow = 0, pznow = 0, panow = 0, pbnow = 0, pcnow = 0;//当前运行到某个位置了
            int px = 0, py = 0, pz = 0, pa = 0, pb = 0, pc = 0;
            double synvel = 1, synacc = 0.5;
            for (int i = 0; i < gcode.Count; i++)
            {
                CGBase c = CGBase.createClass(cmd);
                if (c == null)
                    return -1;
                if (c is CG00)
                {
                    CG00 g0 = c as CG00;
                    var pt = g0.ept;
                    double prfpos = 0;
                    uint clock = 0;
                    mc.GTN_SetG0Mode((short)p.core, (short)p.crdNum, 0);
                    synvel = p.tranCrdVel(g0.cutVel);
                    synacc = p.tranCrdAcc();
                    if (p.Dimension == 2)
                    {
                        if (pt.x != double.MaxValue)
                        {
                            px = (int)p.tranPos("x", g0.ept.x);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                            px = (int)prfpos;
                        }
                        if (pt.y != double.MaxValue)
                        {
                            py = (int)p.tranPos("y", g0.ept.y);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                            py = (int)prfpos;
                        }
                        rtn += mc.GTN_LnXYG0((short)p.core, (short)p.crdNum, px, py, synvel,synacc, 0);
                        cmdCounter++;
                        pxnow = px;
                        pynow = py;
                    }
                    else if (p.Dimension == 3)
                    {
                        if (pt.x != double.MaxValue)
                        {
                            px = (int)p.tranPos("x", g0.ept.x);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                            px = (int)prfpos;
                        }
                        if (pt.y != double.MaxValue)
                        {
                            py = (int)p.tranPos("y", g0.ept.y);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                            py = (int)prfpos;
                        }
                        if (pt.z != double.MaxValue)
                        {
                            pz = (int)p.tranPos("z", g0.ept.z);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[2], out prfpos, 1, out clock);
                            pz = (int)prfpos;
                        }
                        rtn += mc.GTN_LnXYZG0((short)p.core, (short)p.crdNum, px, py, pz, synvel,synacc, 0);
                        cmdCounter++;
                        pxnow = px;
                        pynow = py;
                        pznow = pz;
                    }
                    else if (p.Dimension == 4)
                    {
                        if (pt.x != double.MaxValue)
                        {
                            px = (int)p.tranPos("x", g0.ept.x);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[0], out prfpos, 1, out clock);
                            px = (int)prfpos;
                        }
                        if (pt.y != double.MaxValue)
                        {
                            py = (int)p.tranPos("y", g0.ept.y);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[1], out prfpos, 1, out clock);
                            py = (int)prfpos;
                        }
                        if (pt.z != double.MaxValue)
                        {
                            pz = (int)p.tranPos("z", g0.ept.z);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[2], out prfpos, 1, out clock);
                            pz = (int)prfpos;
                        }
                        if (pt.a != double.MaxValue)
                        {
                            pa = (int)p.tranPos("a", g0.ept.a);
                        }
                        else
                        {
                            rtn += mc.GTN_GetPrfPos((short)p.core, (short)p.axis[3], out prfpos, 1, out clock);
                            pa = (int)prfpos;
                        }
                        rtn += mc.GTN_LnXYZAG0((short)p.core, (short)p.crdNum, px, py, pz, pa, synvel,synacc, 0);
                        cmdCounter++;
                        pxnow = px;
                        pynow = py;
                        pznow = pz;
                        panow = pa;
                    }
                    if (rtn != 0)
                        return rtn;
                    else if (cmdCounter > startSeg && !isStart)
                    {
                        MC_CrdStart(crdID);
                        isStart = true;
                    }
                }
                else if (c is CG01)
                {
                    CG01 g01 = c as CG01;
                    synvel = p.tranCrdVel(g01.cutVel);
                    synacc = p.tranCrdAcc();
                    if (g01.usedAxis == 2)
                    {
                        px = (int)p.tranPos("x", g01.spt.x);
                        py = (int)p.tranPos("y", g01.spt.y);
                        //如果起点和直线起点不同 需要先直线过去
                        if (px != pxnow || py != pynow)
                        {
                            rtn += mc.GTN_LnXY((short)p.core, (short)p.crdNum, px, py, synvel,synacc, synvel, 0);
                            pxnow = px;
                            pynow = py;
                            cmdCounter++;
                        }
                        //计算终点做包
                        px = (int)p.tranPos("x", g01.ept.x);
                        py = (int)p.tranPos("y", g01.ept.y);
                        pa = (int)p.tranPos("a", g01.A);
                        pb = (int)p.tranPos("b", g01.B);
                        if (Math.Abs(pa) != 0)
                        {
                            rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], pa, 0);
                            panow += pa;
                            cmdCounter++;
                        }
                        if (Math.Abs(pb) != 0)
                        {
                            rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], pb, 0);
                            pbnow += pb;
                            cmdCounter++;
                        }
                        rtn += mc.GTN_LnXY((short)p.core, (short)p.crdNum, px,py, synvel,synacc,synvel, 0);
                        pxnow = px;
                        pynow = py;
                        cmdCounter++;
                    }
                    else if (g01.usedAxis == 3)
                    {
                        px = (int)p.tranPos("x", g01.spt.x);
                        py = (int)p.tranPos("y", g01.spt.y);
                        pz = (int)p.tranPos("z", g01.spt.z);
                        //如果起点和直线起点不同 需要先直线过去
                        if (px != pxnow || py != pynow || pz != pznow)
                        {
                            rtn += mc.GTN_LnXYZ((short)p.core, (short)p.crdNum, px, py, pz, synvel, synacc, synvel, 0);
                            pxnow = px;
                            pynow = py;
                            pznow = pz;
                            cmdCounter++;
                        }
                        px = (int)p.tranPos("x", g01.ept.x);
                        py = (int)p.tranPos("y", g01.ept.y);
                        pz = (int)p.tranPos("z", g01.ept.z);
                        pa = (int)p.tranPos("a", g01.A);
                        pb = (int)p.tranPos("b", g01.B);
                        if (Math.Abs(pa) != 0)
                        {
                            rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], pa, 0);
                            panow += pa;
                            cmdCounter++;
                        }
                        if (Math.Abs(pb) != 0)
                        {
                            rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], pb, 0);
                            pbnow += pb;
                            cmdCounter++;
                        }
                        rtn += mc.GTN_LnXYZ((short)p.core, (short)p.crdNum, px, py, pz, synvel, synacc, synvel, 0);
                        pxnow = px;
                        pynow = py;
                        pznow = pz;
                        cmdCounter++;
                    }
                    if (rtn != 0)
                        return rtn;
                    else if (cmdCounter > startSeg && !isStart)
                    {
                        MC_CrdStart(crdID);
                        isStart = true;
                    }
                }
                else if (c is CG02)
                {
                    CG02 a02 = c as CG02;
                    synvel = p.tranCrdVel(a02.cutVel);
                    synacc = p.tranCrdAcc();
                    px = (int)p.tranPos("x", a02.spt.x);
                    py = (int)p.tranPos("y", a02.spt.y);
                    //如果起点和直线起点不同 需要先直线过去
                    if (px != pxnow || py != pynow)
                    {
                        rtn += mc.GTN_LnXY((short)p.core, (short)p.crdNum, px, py, synvel, synacc, synvel, 0);
                        pxnow = px;
                        pynow = py;
                        cmdCounter++;
                    }
                    pa = (int)p.tranPos("a", a02.A);
                    pb = (int)p.tranPos("b", a02.B);
                    if (Math.Abs(pa) != 0)
                    {
                        rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], pa, 0);
                        panow += pa;
                        cmdCounter++;
                    }
                    if (Math.Abs(pb) != 0)
                    {
                        rtn += mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], pb, 0);
                        pbnow += pb;
                        cmdCounter++;
                    }
                    rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, (int)p.tranPos("x", a02.ept.x), (int)p.tranPos("y", a02.ept.y), p.tranPos("x", a02.I), p.tranPos("y", a02.J), (short)a02.direct, p.tranCrdVel(a02.cutVel), p.tranCrdAcc(), p.tranCrdVel(a02.cutVel), 0);
                    cmdCounter++;
                    if (rtn != 0)
                        return rtn;
                    else if (cmdCounter > startSeg && !isStart)
                    {
                        MC_CrdStart(crdID);
                        isStart = true;
                    }
                }
                else if (c is CG03)
                {
                    CG03 a03 = c as CG03;
                    synvel = p.tranCrdVel(a03.cutVel);
                    synacc = p.tranCrdAcc();
                    if (Math.Abs(a03.A) > 0.0000001)
                    {
                        mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[3], (int)p.tranPos("a", a03.A), 0);
                        cmdCounter++;
                    }
                    if (Math.Abs(a03.B) > 0.0000001)
                    {
                        mc.GTN_BufGear((short)p.core, (short)p.crdNum, (short)p.axis[4], (int)p.tranPos("b", a03.B), 0);
                        cmdCounter++;
                    }
                    rtn += mc.GTN_ArcXYC((short)p.core, (short)p.crdNum, (int)p.tranPos("x", a03.ept.x), (int)p.tranPos("y", a03.ept.y), p.tranPos("x", a03.I), p.tranPos("y", a03.J), (short)a03.direct, p.tranCrdVel(a03.cutVel), p.tranCrdAcc(), p.tranCrdVel(a03.cutVel), 0);
                    cmdCounter++;
                    if (rtn != 0)
                        return rtn;
                    else if (cmdCounter > startSeg && !isStart)
                    {
                        MC_CrdStart(crdID);
                        isStart = true;
                    }
                }
                if (cmdCounter >= 4096)
                    break;
            }
            //启动
            //int space = 0;
            //mc.GTN_CrdSpace((short)p.core, (short)p.crdNum, out space, 0);
            int rst = 0;
            if (!isStart)
                rst = MC_CrdStart(crdID);
            return rst;
        }

        public int MC_CrdCheckExist(string crdID)
        {
            CCrdPrmSingle crd = CGlbMc.crdPrm.get(crdID);
            if (crd == null)
                return 0;
            int model = 0;
            //检查每个轴是否是坐标系
            for (int i = 0; i < crd.Dimension; i++)
            {
                mc.GTN_GetPrfMode((short)crd.core, (short)crd.axis[i], out model, 1, out clock);
                if (model != 5)
                    return 0;
            }
            //增量方式 每次必须设置
            if (crd.setCrdAsZeroPos > 0)
            {
                return 0;
            }
            return 1;
        }

        public int MC_CrdCreate(string crdID)
        {
            CCrdPrmSingle crd = CGlbMc.crdPrm.get(crdID);
            if (crd == null)
                return 2;
            if (!crd.ParameterOk)
                return 1;
            //有轴在运动 不允许创建
            int sts = 0;
            int rtn = 0;
            for (int i = 0; i < crd.Dimension; i++)
            {
                mc.GTN_GetSts((short)crd.core, (short)crd.axis[i], out sts, 1, out clock);
                if ((sts & 0x400) != 0)
                    return 1;
            }
            //设置参数
            mc.TCrdPrm prm = new mc.TCrdPrm();
            prm.dimension = (short)crd.Dimension;
            short a = 0;
            for (int i = 0; i < crd.Dimension; i++)
            {
                a = (short)(i+1);
                switch (crd.axis[i])
                {
                    case 1:
                        prm.profile1 = a;
                        break;
                    case 2:
                        prm.profile2 = a;
                        break;
                    case 3:
                        prm.profile3 = a;
                        break;
                    case 4:
                        prm.profile4 = a;
                        break;
                    case 5:
                        prm.profile5 = a;
                        break;
                    case 6:
                        prm.profile6 = a;
                        break;
                    case 7:
                        prm.profile7 = a;
                        break;
                    case 8:
                        prm.profile8 = a;
                        break;
                }
            }
            prm.synAccMax = crd.tranCrdAcc(crd.maxacc);
            prm.synVelMax = crd.tranCrdVel(crd.maxvel);
            prm.evenTime = (short)crd.evenTime;
            //设置坐标系原点
            double posnow = 0.0;
            if (crd.setCrdAsZeroPos > 0)
            {
                for (int i = 0; i < crd.Dimension; i++)
                {
                    mc.GTN_GetPrfPos((short)crd.core, (short)crd.axis[i], out posnow, 1, out clock);
                    switch (crd.axis[i])
                    {
                        case 1:
                            prm.originPos1 = (int)posnow;
                            break;
                        case 2:
                            prm.originPos2 = (int)posnow;
                            break;
                        case 3:
                            prm.originPos3 = (int)posnow;
                            break;
                        case 4:
                            prm.originPos4 = (int)posnow;
                            break;
                        case 5:
                            prm.originPos5 = (int)posnow;
                            break;
                        case 6:
                            prm.originPos6 = (int)posnow;
                            break;
                        case 7:
                            prm.originPos7 = (int)posnow;
                            break;
                        case 8:
                            prm.originPos8 = (int)posnow;
                            break;
                    }
                }
                prm.setOriginFlag = 1;//当前坐标系
            }
            else
            {
                prm.setOriginFlag = 1;
            }
            rtn = mc.GTN_SetCrdPrm((short)crd.core, (short)crd.crdNum, ref prm);
            rtn += mc.GTN_CrdClear((short)crd.core, (short)crd.crdNum,0);
            rtn += mc.GTN_CrdClear((short)crd.core, (short)crd.crdNum, 1);
            return rtn;
        }

        public int MC_CrdPause(string crdID)
        {
            CCrdPrmSingle crd = CGlbMc.crdPrm.get(crdID);
            if (crd == null)
                return 1;
            //停止一个轴 就会停止坐标系
            short rtn = mc.GTN_Stop((short)crd.core, (short)(1 << (crd.axis[0] - 1)), 0);
            return rtn;
        }

        public int MC_CrdStop(string crdID)
        {
            CCrdPrmSingle crd = CGlbMc.crdPrm.get(crdID);
            if (crd == null)
                return 1;
            //停止一个轴 就会停止坐标系
            short rtn = mc.GTN_Stop((short)crd.core, (short)(1 << (crd.axis[0] - 1)), 0);
            return rtn;
        }

        /// <summary>
        /// GSN的扩展模块划分按照轴模块,扩展模块来划分
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool MC_GetModel(CIoModel data)
        {
            var p = data.prm;
            UInt32[] value = new UInt32[4];//暂时认为最大的是4组
            bool isLocal = p.IsLocal;//确认是本地还是扩展模块
            short coreID = (short)p.CardIDOrModelID;
            short extID = (short)p.ExtModelID;
            short lenth = 0;
            short rtn = 0;
            int DataStart = 0;
            int bitStart = 0; 
            UInt32 datanow = 0;
            int index = 0;
            //uint clock = 0;
            if (data.DiCount > 0)
            {
                DataStart = p.diDataStart;
                lenth = data.DiCount;
                bitStart = p.DiStartIndex;
                if (isLocal)
                {
                    int bitcount = (bitStart + lenth) / 32 + 1;
                    rtn = mc.GTN_GetDiEx(coreID, mc.MC_GPI, out value[0], (short)bitcount);
                    
                    for (int i = 0; i < lenth; i++)
                    {
                        index = (bitStart + i) / 32;
                        datanow = value[index];
                        index = (bitStart + i) % 32;
                        CMotionManager.diData[DataStart + i] = !CMathTool.getBit(datanow, index);
                    }
                }
                else
                {
                    //TODO:需要再测试,考虑更多的问题.
                    rtn = mc.GTN_GetExtDi(coreID, mc.MC_GPI, out value[0]);
                    for (int i = 0; i < lenth; i++)
                    {
                        CMotionManager.diData[DataStart + i] = !CMathTool.getBit(value[0], bitStart + i);
                    }
                }
            }
            if (data.DoCount >0)
            {
                DataStart = p.doDataStart;
                lenth = data.DoCount;
                bitStart = p.DoStartIndex;
                if (isLocal)
                {
                    int bitcount = (bitStart + lenth) / 32 + 1;
                    rtn = mc.GTN_GetDoEx(coreID, mc.MC_GPO, out value[0], (short)bitcount);
                    for (int i = 0; i < lenth; i++)
                    {
                        index = (bitStart + i) / 32;
                        datanow = value[index];
                        index = (bitStart + i) % 32;
                        CMotionManager.doData[DataStart + i] = !CMathTool.getBit(datanow, index);
                    }
                }
                else
                {
                    //TODO:还没考虑扩展模块输出问题.
                    rtn = mc.GTN_GetExtDo(coreID, (short)bitStart, out value[0]);
                    for (int i = 0; i < lenth; i++)
                    {
                        CMotionManager.doData[DataStart + i] = !CMathTool.getBit(value[0], i);
                    }
                }
            }
            //TODO:增加模拟量和编码器读取
            //if (p.aiDataLenth > 0)
            //{
            //    if (isLocal)
            //    {

            //        //mc.GTN_GetDac(coreID, mc.MC_ADC, out value);
            //    }
            //    else
            //    {
            //        //mc.GTN_GetExtDi(coreID, mc.MC_GPI, out value);
            //    }
            //}
            //if (p.aoDataLenth > 0)
            //{

            //}
            //if (p.encDataLenth > 0)
            //{

            //}
            return true;
        }

        public bool MC_GetIO(ref CIO_Di data)
        {
            var p = data.prm;
            short cardID = p.CardIDOrModelID;
            short value = 0;
            short index = p.startIndex;
            if (p.IsLocal)
            {
                uint ct = 0;
                mc.GTN_GetDiReverseCount(cardID, mc.MC_GPI, index, out ct, 1);
                data.counter = ct;
                mc.GTN_GetDiBit(cardID, mc.MC_GPI, index,out value);
                CMotionManager.diData[p.dIndex] = value != 0;
            }
            else
            {
                mc.GTN_GetExtDiBit(cardID, index, out value);
                CMotionManager.diData[p.dIndex] = value != 0;
            }
            return CMotionManager.diData[p.dIndex];
        }

        public bool MC_GetIO(CIO_Do data)
        {
            var p = data.prm;
            short cardID = p.CardIDOrModelID;
            uint value = 0;
            short index = p.startIndex;
            if (p.IsLocal)
            {
                mc.GTN_GetDo(cardID, mc.MC_GPO, out value);
                CMotionManager.doData[p.dIndex] = CMathTool.getBit(value,p.startIndex);
            }
            else
            {
                mc.GTN_GetExtDo(cardID, mc.MC_GPO, out value);
                CMotionManager.doData[p.dIndex] = CMathTool.getBit(value, p.startIndex);
            }
            return CMotionManager.doData[p.dIndex];
        }

        public float MC_GetIO(CIO_Ai data)
        {
            short core = data.prm.CardIDOrModelID;
            short index = data.prm.startIndex;
            double value = 0;
            uint clock = 0;
            if (data.prm.IsLocal)
            {
                mc.GTN_GetAdc(core, index, out value, 1, out clock);
                CMotionManager.aiData[data.prm.dIndex] = (float)value;
                return (float)value;
            }
            else
            {
                mc.GTN_GetExtAi(core, index, out value, 1);
                CMotionManager.aiData[data.prm.dIndex] = (float)value;
                return (float)value;
            }
        }

        public float MC_GetIO(CIO_Ao data)
        {
            short core = data.prm.CardIDOrModelID;
            short index = data.prm.startIndex;
            uint clock = 0;
            if (data.prm.IsLocal)
            {
                short value = 0;
                mc.GTN_GetDac(core, index, out value, 1, out clock);
                CMotionManager.aiData[data.prm.dIndex] = (float)value;
                return (float)value;
            }
            else
            {
                uint value = 0;
                mc.GTN_GetExtDo(core, index, out value);
                CMotionManager.aiData[data.prm.dIndex] = (float)value;
                return (float)value;
            }
        }

        public long MC_GetIO(CIO_Enc data)
        {
            throw new NotImplementedException();
        }

        public bool MC_SetDo(CIO_Do data, bool value)
        {
            short core = data.prm.CardIDOrModelID;
            short index = (short)(data.prm.startIndex+1);
            int setvalue = value?0:1;
            if (data.prm.IsLocal)
            {
                mc.GTN_SetDoBit(core, mc.MC_GPO, index, (short)setvalue);
            }
            else
            {
                mc.GTN_SetExtDoBit(core, index, (short)setvalue);
            }
            return true;
        }

        public bool MC_SetDo(CIO_Ao data, float value)
        {
            short rtn = 0;
            short core = data.prm.CardIDOrModelID;
            short index = data.prm.startIndex;
            short setvalue = (short)value;
            if (data.prm.IsLocal)
            {
                rtn = mc.GTN_SetDac(core,index, ref setvalue,1);
            }
            else
            {
                rtn = mc.GTN_SetExtDoBit(core, index, (short)setvalue);
            }
            return rtn == 0;
        }

        public int MC_BuffControl(List<string> cmdList)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// TODO:需要测试
        /// </summary>
        /// <param name="prm"></param>
        /// <returns></returns>
        public int MC_AxisRef(CAxisModelPrm prm)
        {
            const int maxAxis = 32;
            int[] sts = new int[maxAxis];
            uint clock = 0;
            double[] prfpos = new double[maxAxis], encpos = new double[maxAxis], prfvel = new double[maxAxis], encvel = new double[maxAxis];
            int homeswitch = 0, lmtpswitch = 0, lmtnswitch = 0;
            short rtn = 0;
            short cardNum = (short)prm.CardIDOrModelID;
            short startIndex = (short)(prm.StartIndex + 1);
            short axisCount = (short)prm.AxisCount;
            short dStartIndex = (short)prm.StartIndexData;
            bool readprfvel = CAxisModelPrm.ReadPrfVel;
            bool readencvel = CAxisModelPrm.ReadEncVel;
            bool readsw = CAxisModelPrm.ReadSW;
            //必须度
            rtn += mc.GTN_GetSts(cardNum, startIndex, out sts[0], axisCount, out clock);
            rtn += mc.GTN_GetPrfPos(cardNum, startIndex, out prfpos[0], axisCount, out clock);
            rtn += mc.GTN_GetEncPos(cardNum, startIndex, out encpos[0], axisCount, out clock);
            //可读写
            if(readprfvel)
                rtn += mc.GTN_GetPrfVel(cardNum, startIndex, out prfvel[0], axisCount, out clock);
            if(readencvel)
                rtn += mc.GTN_GetEncVel(cardNum, startIndex, out encvel[0], axisCount, out clock);
            if(readsw)
            {
                rtn += mc.GTN_GetDi(cardNum, mc.MC_HOME, out homeswitch);
                rtn += mc.GTN_GetDi(cardNum, mc.MC_LIMIT_POSITIVE, out lmtpswitch);
                rtn += mc.GTN_GetDi(cardNum, mc.MC_LIMIT_NEGATIVE, out lmtnswitch);
            }
            if (rtn != 0)
                return rtn;
            var ds = CMotionManager.axisData;
            for (int i = 0; i < axisCount; i++)
            {
                var axisref = ds[i + dStartIndex];
                axisref.swHome = ((1 << (startIndex + i - 1)) & homeswitch) == 0;
                axisref.swLmtP = ((1 << (startIndex + i - 1)) & lmtpswitch) == 0;
                axisref.swLmtN = ((1 << (startIndex + i - 1)) & lmtnswitch) == 0;
                axisref.alarm = (sts[i] & 0x2) != 0;
                axisref.servoOn = (sts[i] & 0x200) != 0;
                axisref.limitN = (sts[i] & 0x40) != 0;
                axisref.limitP = (sts[i] & 0x20) != 0;
                axisref.moving = (sts[i] & 0x400) != 0;
                axisref.cmdPos = (float)axisref.prm.pls2mm((long)prfpos[i]);
                axisref.cmdVel = (float)axisref.prm.plsperms2mmpers(prfvel[i]);
                axisref.relPos = (float)axisref.prm.pls2mm((long)encpos[i]);
                axisref.relVel = (float)axisref.prm.plsperms2mmpers(encvel[i]);
            }
            return 0;
        }

        public int compare()
        {
            throw new NotImplementedException();
        }

        public int MC_Compare(CAxisRef axis, double posMM, CIO_Do cmpInput)
        {
            throw new NotImplementedException();
        }
    }
}
